/*
    IceCode toolkit - maths
    Copyright (C) 2011 Alfredo 'IceCoder' Mungo

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <icecode/test/TimedTest.hpp>
#include "../Vector.hpp"

using namespace icecode;
using namespace icecode::test;

class VectorTest : public TimedTest
{
public:
  VectorTest() : TimedTest("Testing the Vector class...")
  {
  }

  void run()
  {
    double dl[] = {1, 2, 4};
    maths::Vector3d v1, v2, v3(dl), v4(v3), v5({1, 2, 3});
    maths::Vector2f v6({1, 2}), v7({3, 4});

    assert_fatal(v1[0] == 0 && v1[1] == 0 && v1[2] == 0, "Empty constructor (and clear() method).", 1);
    assert_fatal(v3[0] == 1 && v3[1] == 2 && v3[2] == 4, "List constructor.", 1);
    assert_fatal(v4[0] == 1 && v4[1] == 2 && v4[2] == 4, "Copy constructor.", 1);

    v1[0] = 1;
    v1[2] = 4;

    assert(v1[0] == 1 && v1[2] == 4, "Element assignment 1.");

    v1[0] = 2;
    v1[2] = 1;

    assert(v1[0] == 2 && v1[2] == 1, "Element assignment 2.");

    v1[1] = 5;
    v2 = v1;
    assert(v2[0] == 2 && v2[1] == 5 && v2[2] == 1, "Assignment operator.");

    v1 = {1, 4, 8};
    assert(v1[0] == 1 && v1[1] == 4 && v1[2] == 8, "List assignment operator.");

    assert(v3 == v4, "Equality operator");
    v2 *= 3;
    assert(v2[0] == 6 && v2[1] == 15 && v2[2] == 3, "Multiplication-equal operator.");
    v2 /= 3;
    assert(v2[0] == 2 && v2[1] == 5 && v2[2] == 1, "Division-equal operator.");

    v1 = {0, 0, 0};
    v1 = v2 * 3;
    assert(v1[0] == 6 && v1[1] == 15 && v1[2] == 3, "Multiplication operator.");
    v3 = v1 / 3;
    assert(v3[0] == 2 && v3[1] == 5 && v3[2] == 1, "Division operator.");

    double *v = v2.getData();
    assert(v[0] == 2 && v[1] == 5 && v[2] == 1, "Raw data gathering.");

    v2 = {0, 4, 3};
    assert(v2.magnitude() == 5, "Magnitude computation.");

    v1 = {3, 9, 0};
    v2 = {4, 8, 0};
    assert(v1.dot(v2) == 84, "Dot product computation.");

    v1 = {12, 4, 5};
    v2 = {8, 7, 9};
    v3 = {1, -68, 52};
    assert(v1.cross(v2) == v3, "Cross product computation.");

    except(v6.cross(v7), "Cross product, invalid vector exception.");

    except_begin
      {
	v7 = {1, 2, 3};
      }
    except_end("List assignment operator, size mismatch exception.");
  }
};
